package com.liuyi.netty.im.server.handle;

import com.liuyi.netty.im.commons.codes.CodeConst;
import com.liuyi.netty.im.commons.codes.LimProtocol;
import com.liuyi.netty.im.server.handle.storage.ChannelStorage;
import com.liuyi.netty.im.server.util.ImHelp;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.RejectedExecutionException;

/**
 * @author Mr.Fmy
 * @since 2021-11-23
 */
@Slf4j
public class LimChannelHandler extends SimpleChannelInboundHandler<LimProtocol> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, LimProtocol message) throws Exception {
        if (message.getCommand().equals(CodeConst.Command.HEARTBEAT)) {
//            //心跳直接过滤掉
            return;
        }
        //接收到消息
        log.debug("收到客户端消息：" + message.toString());
        Runnable runnable = () -> {
            try {
                if (message.getData() != null) {
                    LimComandService.get(message.getCommand()).getObject1().processor(ctx, message.getData());
                } else {
                    LimComandService.get(message.getCommand()).getObject1().processor(ctx, null);
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        };
        try {
            LimComandService.get(message.getCommand()).getObject2().execute(runnable);
        } catch (RejectedExecutionException ex) {
            log.warn("Reject ImServer request,cause={}", ex.getMessage());
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.debug(ctx.channel().id().asLongText() + " close");
        ImHelp.logout(ctx.channel());
        ChannelStorage.remove(ctx.channel());
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleState state = ((IdleStateEvent) evt).state();
            if (state == IdleState.READER_IDLE) {
                // 在规定时间内没有收到客户端的上行数据, 主动断开连接
                ctx.channel().close();
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}
